package com.example.photo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.photo.common.ErrorCode;
import com.example.photo.exception.BusinessException;
import com.example.photo.mapper.ScoreMapper;
import com.example.photo.mapper.WorkMapper;
import com.example.photo.model.domain.Score;
import com.example.photo.model.domain.Work;
import com.example.photo.service.ScoreService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * @author 85792
 * @description 针对表【score(打分)】的数据库操作Service实现
 * @createDate 2023-03-25 19:15:26
 */
@Service
public class ScoreServiceImpl extends ServiceImpl<ScoreMapper, Score>
        implements ScoreService {

    @Resource
    private ScoreMapper scoreMapper;

    @Resource
    private WorkMapper workMapper;

    /**
     * 新增或修改打分记录
     *
     * @param workId        作品id
     * @param userId        打分人id
     * @param newScoreValue 分数
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    @Override
    public synchronized void doScore(Integer workId, Integer userId, Integer newScoreValue) {
        //试图获取该作品
        Work work = workMapper.selectById(workId);
        if (work == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "该作品不存在");
        }
        //旧 均分
        BigDecimal oldAve = work.getAverage();
        //旧 打分人数
        Integer oldNum = work.getScorerNum();

        //试图获取打分记录
        QueryWrapper<Score> scoreQueryWrapper = new QueryWrapper<>();
        scoreQueryWrapper.eq("work_id", workId);
        scoreQueryWrapper.eq("scorer_id", userId);
        Score oldScore = scoreMapper.selectOne(scoreQueryWrapper);
        if (oldScore == null) {
            //当前账号没有给该作品打过分，插入
            Score insertScore = new Score();
            insertScore.setScore(newScoreValue);
            insertScore.setWorkId(workId);
            insertScore.setScorerId(userId);
            int insert = scoreMapper.insert(insertScore);
            if (insert < 1) {
                throw new BusinessException(ErrorCode.SERVER_ERROR, "保存打分记录失败");
            }

            //更新打分人数和均分
            //新 打分人数
            int newNum = oldNum + 1;
            //新 均分
            BigDecimal newAve = oldAve
                    .multiply(BigDecimal.valueOf(oldNum))
                    .add(BigDecimal.valueOf(newScoreValue))
                    .divide(BigDecimal.valueOf(newNum), RoundingMode.HALF_DOWN);
            Work updateWork = new Work();
            updateWork.setWorkId(workId);
            updateWork.setScorerNum(newNum);
            updateWork.setAverage(newAve);
            int update = workMapper.updateById(updateWork);
            if (update < 1) {
                throw new BusinessException(ErrorCode.SERVER_ERROR, "修改均分失败");
            }
        } else {
            Integer oldScoreValue = oldScore.getScore();
            //当前账号已经给该作品打过分，修改
            oldScore.setScore(newScoreValue);
            int update = scoreMapper.updateById(oldScore);
            if (update < 1) {
                throw new BusinessException(ErrorCode.SERVER_ERROR, "修改打分记录失败");
            }

            //更新均分
            //新 均分
            BigDecimal newAve = oldAve
                    .multiply(BigDecimal.valueOf(oldNum))
                    .add(BigDecimal.valueOf(oldScoreValue).negate())
                    .add(BigDecimal.valueOf(newScoreValue))
                    .divide(BigDecimal.valueOf(oldNum), RoundingMode.HALF_DOWN);
            Work updateWork = new Work();
            updateWork.setWorkId(workId);
            updateWork.setAverage(newAve);
            update = workMapper.updateById(updateWork);
            if (update < 1) {
                throw new BusinessException(ErrorCode.SERVER_ERROR, "修改均分失败");
            }
        }
    }
}




